home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Dev / Obrn-A_1.6_lib.lha / oberon-a / source3.lha / source / Library / Files.mod < prev    next >
Text File  |  1995-06-29  |  16KB  |  702 lines

  1. (*************************************************************************
  2.  
  3.      $RCSfile: Files.mod $
  4.   Description: Operations on files and the file directory.
  5.  
  6.    Created by: fjc (Frank Copeland)
  7.     $Revision: 1.13 $
  8.       $Author: fjc $
  9.         $Date: 1995/06/04 23:22:41 $
  10.  
  11.   Copyright © 1994-1995, Frank Copeland.
  12.   This file is part of the Oberon-A Library.
  13.   See Oberon-A.doc for conditions of use and distribution.
  14.  
  15. *************************************************************************)
  16.  
  17. <* STANDARD- *>
  18.  
  19. MODULE Files;
  20.  
  21. IMPORT
  22.   SYS := SYSTEM, Kernel, e := Exec, d := Dos, du := DosUtil,
  23.   str := Strings, conv := Conversions, oc := OberonClock;
  24.  
  25. CONST
  26.   SectorSize = 1024;
  27.   MaxBufs = 4;
  28.  
  29. TYPE
  30.  
  31.   File *= POINTER TO Handle;
  32.  
  33.   Buffer = POINTER TO BufferRecord;
  34.  
  35.   Rider *= RECORD
  36.     eof -: BOOLEAN;
  37.     res -: LONGINT;
  38.     file : File;
  39.     pos : LONGINT;
  40.     buf : Buffer;
  41.     bpos : INTEGER;
  42.   END; (* Rider *)
  43.  
  44.   Handle = RECORD
  45.     fl -: d.FileLockPtr;
  46.     fh -: d.FileHandlePtr;
  47.     name : ARRAY 256 OF CHAR;
  48.     tempNo : LONGINT;
  49.     pos, len : LONGINT;
  50.     nofbufs : INTEGER;
  51.     next : File;
  52.     firstbuf : Buffer;
  53.   END; (* Handle *)
  54.  
  55.   DataSector = ARRAY SectorSize OF SYS.BYTE;
  56.  
  57.   BufferRecord = RECORD
  58.     apos : LONGINT;
  59.     lim : INTEGER;
  60.     mod : BOOLEAN;
  61.     next : Buffer;
  62.     data : DataSector;
  63.   END; (* BufferRecord *)
  64.  
  65.  
  66. VAR
  67.   root : File;
  68.   tempNo : LONGINT;
  69.  
  70. CONST
  71.   tempExt = ".tmp";
  72.   bkpExt = ".bkp";
  73.  
  74.  
  75. PROCEDURE GetTempNo;
  76.  
  77.   VAR time, date : LONGINT;
  78.  
  79. BEGIN (* GetTempNo *)
  80.   oc.GetClock (time, date);
  81.   tempNo := ABS ((date * 10000H + time) DIV 2)
  82. END GetTempNo;
  83.  
  84.  
  85. PROCEDURE MakeName
  86.   ( name : ARRAY OF CHAR;
  87.     tempNo : LONGINT;
  88.     ext : ARRAY OF CHAR;
  89.     VAR tempName : ARRAY OF CHAR );
  90.  
  91.   VAR pathPart : e.LSTRPTR; s : ARRAY 13 OF CHAR;
  92.  
  93. <*$CopyArrays-*>
  94. BEGIN (* MakeName *)
  95.   COPY (name, tempName);
  96.   IF tempName # "" THEN
  97.     pathPart := d.PathPart (tempName); pathPart [0] := 0X
  98.   END;
  99.   ASSERT (conv.IntToStr (tempNo, 16, 0, "0", s));
  100.   str.Append (ext, s);
  101.   ASSERT (d.AddPart (tempName, s, LEN (tempName)))
  102. END MakeName;
  103.  
  104.  
  105. PROCEDURE Search ( fl : d.FileLockPtr ) : File;
  106.  
  107.   VAR f : File;
  108.  
  109. BEGIN (* Search *)
  110.   f := root;
  111.   WHILE (f # NIL) & (d.SameLock (fl, f.fl) # d.same) DO f := f.next END;
  112.   RETURN f
  113. END Search;
  114.  
  115.  
  116. PROCEDURE Unlink (f : File);
  117.  
  118.   VAR f0 : File;
  119.  
  120. BEGIN (* Unlink *)
  121.   IF root # NIL THEN
  122.     IF f = root THEN
  123.       root := root.next
  124.     ELSE
  125.       f0 := root;
  126.       WHILE (f0.next # NIL) & (f0.next # f) DO
  127.         f0 := f0.next
  128.       END;
  129.       IF f0.next = f THEN f0.next := f.next END;
  130.     END
  131.   END;
  132.   f.next := NIL
  133. END Unlink;
  134.  
  135.  
  136. PROCEDURE ReadBuf (f : File; buf : Buffer; pos : LONGINT);
  137.  
  138.   VAR res : LONGINT;
  139.  
  140. BEGIN (* ReadBuf *)
  141.   res := d.Seek (f.fh, pos, d.beginning);
  142.   IF res # -1 THEN
  143.     buf.lim := SHORT (d.Read (f^.fh, buf.data, SectorSize));
  144.     buf.apos := pos;
  145.     buf.mod := FALSE;
  146.   END
  147. END ReadBuf;
  148.  
  149.  
  150. PROCEDURE WriteBuf (f : File; buf : Buffer);
  151.  
  152.   VAR res : LONGINT;
  153.  
  154. BEGIN (* WriteBuf *)
  155.   res := d.Seek (f.fh, buf.apos, d.beginning);
  156.   IF res # -1 THEN
  157.     res := d.Write (f.fh, buf.data, buf.lim);
  158.     IF res = buf.lim THEN
  159.       buf.mod := FALSE;
  160.     END
  161.   END
  162. END WriteBuf;
  163.  
  164.  
  165. PROCEDURE GetBuf (f : File; pos : LONGINT) : Buffer;
  166.  
  167.   VAR buf, last, next : Buffer;
  168.  
  169. BEGIN (* GetBuf *)
  170.   buf := f.firstbuf;
  171.   LOOP
  172.     IF buf.apos = pos THEN EXIT END;
  173.     IF buf.next = f.firstbuf THEN
  174.       last := buf;
  175.       IF f.nofbufs < MaxBufs THEN (* allocate new buffer *)
  176.         NEW (buf); INC (f.nofbufs);
  177.       ELSE (* take one of the buffers (assuming more than one) *)
  178.         buf := f.firstbuf; f.firstbuf := buf.next; last.next := buf.next;
  179.         IF buf.mod THEN WriteBuf (f, buf) END
  180.       END;
  181.       IF pos < f.firstbuf.apos THEN
  182.         f.firstbuf := buf
  183.       ELSIF pos < last.apos THEN
  184.         WHILE last.next.apos < pos DO last := last.next END;
  185.       END;
  186.       buf.next := last.next; last.next := buf;
  187.       buf.apos := pos; buf.lim := 0; buf.mod := FALSE;
  188.       IF pos < f.len THEN ReadBuf (f, buf, pos) END;
  189.       EXIT
  190.     END;
  191.     buf := buf.next
  192.   END; (* LOOP *)
  193.   RETURN buf;
  194. END GetBuf;
  195.  
  196.  
  197. PROCEDURE Unbuffer (f : File);
  198.  
  199.   VAR buf : Buffer;
  200.  
  201. BEGIN (* Unbuffer *)
  202.   buf := f.firstbuf;
  203.   REPEAT
  204.     IF buf.mod THEN WriteBuf (f, buf) END;
  205.     buf := buf.next
  206.   UNTIL buf = f.firstbuf
  207. END Unbuffer;
  208.  
  209.  
  210. PROCEDURE Delete * ( name : ARRAY OF CHAR; VAR res : INTEGER );
  211. <*$CopyArrays-*>
  212. BEGIN (* Delete *)
  213.   IF d.DeleteFile (name) THEN
  214.     res := 0
  215.   ELSE
  216.     res := SHORT (d.IoErr ());
  217.     IF res = d.objectNotFound THEN res := 0 END
  218.   END
  219. END Delete;
  220.  
  221.  
  222. PROCEDURE Rename * ( old, new : ARRAY OF CHAR; VAR res : INTEGER );
  223. <*$CopyArrays-*>
  224. BEGIN (* Rename *)
  225.   IF d.Rename (old, new) THEN res := 0
  226.   ELSE res := SHORT (d.IoErr ())
  227.   END
  228. END Rename;
  229.  
  230.  
  231. PROCEDURE Old * ( name : ARRAY OF CHAR ) : File;
  232.  
  233.   VAR
  234.     f : File; fl : d.FileLockPtr; fh : d.FileHandlePtr;
  235.     fib : d.FileInfoBlockPtr; len : LONGINT; buf : Buffer;
  236.  
  237. <*$CopyArrays-*>
  238. BEGIN (* Old *)
  239.   fl := d.Lock (name, d.sharedLock);
  240.   IF fl # NIL THEN
  241.     f := Search (fl);
  242.     IF f = NIL THEN
  243.       fh := d.Open (name, d.oldFile);
  244.       IF fh # NIL THEN
  245.         fib := d.AllocDosObjectTags (d.fib, NIL);
  246.         IF fib # NIL THEN
  247.           IF d.Examine (fl, fib^) THEN len := fib.size;
  248.           ELSE len := 0
  249.           END;
  250.           d.FreeDosObject (d.fib, fib);
  251.           NEW (f);
  252.           IF f # NIL THEN
  253.             NEW (buf);
  254.             IF buf # NIL THEN
  255.               buf.apos := 0; buf.next := buf; buf.mod := FALSE;
  256.               IF len > SectorSize THEN buf.lim := SectorSize
  257.               ELSE buf.lim := SHORT (len)
  258.               END;
  259.               f.len := len; f.firstbuf := buf; f.nofbufs := 1;
  260.               COPY (name, f.name); f.tempNo := 0;
  261.               f.fl := fl; f.fh := fh; f.pos := 0;
  262.               f.next := root; root := f;
  263.               ReadBuf (f, buf, 0);
  264.               RETURN f
  265.             END;
  266.           END;
  267.         END;
  268.       END;
  269.       d.OldClose (fh)
  270.     END;
  271.     d.UnLock (fl)
  272.   END;
  273.   RETURN f
  274. END Old;
  275.  
  276.  
  277. PROCEDURE New * ( name : ARRAY OF CHAR ) : File;
  278.  
  279.   VAR
  280.     f : File; fl : d.FileLockPtr; fh : d.FileHandlePtr;
  281.     buf : Buffer; tempName : ARRAY 256 OF CHAR;
  282.  
  283. <*$CopyArrays-*>
  284. BEGIN (* New *)
  285.   REPEAT
  286.     IF tempNo < MAX (LONGINT) THEN INC (tempNo) ELSE tempNo := 1 END;
  287.     MakeName (name, tempNo, tempExt, tempName)
  288.   UNTIL ~du.FileExists (tempName);
  289.   fh := d.Open (tempName, d.newFile);
  290.   IF fh # NIL THEN
  291.     NEW (f);
  292.     IF f # NIL THEN
  293.       NEW (buf);
  294.       IF buf # NIL THEN
  295.         buf.apos := 0; buf.next := buf; buf.mod := TRUE;
  296.         buf.lim := 0;
  297.         f.len := 0; f.firstbuf := buf; f.nofbufs := 1;
  298.         COPY (name, f.name); f.tempNo := tempNo;
  299.         f.fl := d.Lock (tempName, d.sharedLock); f.fh := fh; f.pos := 0;
  300.         f.next := root; root := f;
  301.         ReadBuf (f, buf, 0);
  302.         RETURN f
  303.       END
  304.     END
  305.   END;
  306.   d.OldClose (fh);
  307.   RETURN f
  308. END New;
  309.  
  310.  
  311. PROCEDURE Register * ( f : File );
  312.  
  313.   VAR tempName, bkpName : ARRAY 256 OF CHAR; res : INTEGER;
  314.  
  315. BEGIN (* Register *)
  316.   ASSERT (f # NIL, 97);
  317.   IF f.fh # NIL THEN
  318.     Unbuffer (f); Unlink (f);
  319.     IF d.Close (f.fh) THEN
  320.       f.fh := NIL; d.UnLock (f.fl); f.fl := NIL;
  321.       IF f.tempNo # 0 THEN
  322.         MakeName (f.name, f.tempNo, tempExt, tempName);
  323.         IF f.name = "" THEN
  324.           Delete (tempName, res);
  325.         ELSE
  326.           MakeName (f.name, f.tempNo, bkpExt, bkpName);
  327.           Rename (f.name, bkpName, res);
  328.           IF res = 0 THEN
  329.             Rename (tempName, f.name, res);
  330.             IF res = 0 THEN Delete (bkpName, res) END
  331.           ELSIF res = d.objectNotFound THEN
  332.             Rename (tempName, f.name, res);
  333.           END
  334.         END
  335.       END
  336.     END
  337.   END
  338. END Register;
  339.  
  340.  
  341. PROCEDURE Close * ( f : File );
  342. BEGIN (* Close *)
  343.   ASSERT (f # NIL, 97);
  344.   IF f.fh # NIL THEN
  345.     Unbuffer (f); Unlink (f);
  346.     IF d.Close (f.fh) THEN f.fh := NIL; d.UnLock (f.fl); f.fl := NIL END
  347.   END
  348. END Close;
  349.  
  350.  
  351. PROCEDURE Purge * ( f : File );
  352.  
  353.   VAR tempName : ARRAY 256 OF CHAR; res : INTEGER;
  354.  
  355. BEGIN (* Purge *)
  356.   ASSERT (f # NIL, 97);
  357.   IF f.fh # NIL THEN
  358.     Unbuffer (f); Unlink (f);
  359.     IF d.Close (f.fh) THEN f.fh := NIL; d.UnLock (f.fl); f.fl := NIL END;
  360.     IF f.tempNo # 0 THEN
  361.       MakeName (f.name, f.tempNo, tempExt, tempName);
  362.       Delete (tempName, res)
  363.     END
  364.   END
  365. END Purge;
  366.  
  367.  
  368. PROCEDURE Length * ( f : File ) : LONGINT;
  369.  
  370. BEGIN (* Length *)
  371.   ASSERT (f # NIL, 97);
  372.   RETURN f.len
  373. END Length;
  374.  
  375.  
  376. PROCEDURE GetDate * ( f : File; VAR time, day : LONGINT );
  377.  
  378.   VAR fib : d.FileInfoBlockPtr;
  379.  
  380. BEGIN (* GetDate *)
  381.   ASSERT (f # NIL, 97); ASSERT (f.fh # NIL, 97);
  382.   fib := d.AllocDosObjectTags (d.fib, NIL);
  383.   IF fib # NIL THEN
  384.     IF d.ExamineFH (f.fh, fib^) THEN
  385.       oc.ADOS2OberonTime (fib.date, time, day);
  386.     END;
  387.     d.FreeDosObject (d.fib, fib)
  388.   END
  389. END GetDate;
  390.  
  391.  
  392. PROCEDURE Set * ( VAR r : Rider; f : File; pos : LONGINT );
  393.  
  394. BEGIN (* Set *)
  395.   r.eof := FALSE; r.res := 0; r.file := f;
  396.   IF f # NIL THEN
  397.     IF pos < 0 THEN r.pos := 0; r.bpos := 0
  398.     ELSE r.bpos := SHORT (pos MOD SectorSize); r.pos := pos - r.bpos
  399.     END;
  400.     r.buf := f.firstbuf
  401.   END
  402. END Set;
  403.  
  404.  
  405. PROCEDURE Pos * ( VAR r : Rider ) : LONGINT;
  406. BEGIN (* Pos *)
  407.   RETURN r.pos + r.bpos
  408. END Pos;
  409.  
  410.  
  411. PROCEDURE Base * ( VAR r : Rider ) : File;
  412. BEGIN (* Base *)
  413.   RETURN r.file
  414. END Base;
  415.  
  416.  
  417. PROCEDURE Read * ( VAR r : Rider; VAR x : SYS.BYTE );
  418.  
  419.   VAR buf : Buffer;
  420.  
  421. BEGIN (* Read *)
  422.   ASSERT (r.file # NIL, 97);
  423.   IF r.pos # r.buf.apos THEN r.buf := GetBuf (r.file, r.pos) END;
  424.   IF r.bpos < r.buf.lim THEN
  425.     x := r.buf.data [r.bpos]; INC (r.bpos)
  426.   ELSIF (r.pos + SectorSize) < r.file.len THEN
  427.     INC (r.pos, SectorSize);
  428.     r.buf := GetBuf (r.file, r.pos);
  429.     x := r.buf.data [0]; r.bpos := 1
  430.   ELSE
  431.     x := 0X; r.eof := TRUE
  432.   END
  433. END Read;
  434.  
  435.  
  436. PROCEDURE ReadBytes * ( VAR r : Rider; VAR x : ARRAY OF SYS.BYTE;
  437.                           n : LONGINT );
  438.  
  439.   VAR src, dst, m : LONGINT;
  440.       buf : Buffer;
  441.  
  442. BEGIN (* ReadBytes *)
  443.   ASSERT (r.file # NIL, 97); ASSERT (r.file.fh # NIL, 97);
  444.   ASSERT (LEN (x) >= n, 97);
  445.   dst := SYS.VAL (LONGINT, SYS.ADR (x));
  446.   IF r.pos # r.buf.apos THEN r.buf := GetBuf (r.file, r.pos) END;
  447.   LOOP
  448.     IF n <= 0 THEN EXIT END;
  449.     src := SYS.VAL (LONGINT, SYS.ADR(r.buf.data));
  450.     INC (src, r.bpos); m := r.bpos + n;
  451.     IF m <= r.buf.lim THEN
  452.       SYS.MOVE (src, dst, n); r.bpos := SHORT (m); r.res := 0;
  453.       EXIT
  454.     ELSIF r.buf.lim = SectorSize THEN
  455.       m := r.buf.lim - r.bpos;
  456.       IF m > 0 THEN
  457.         SYS.MOVE (src, dst, m); INC (dst, m); DEC (n, m)
  458.       END;
  459.       IF r.pos < r.file.len THEN
  460.         INC (r.pos, SectorSize);
  461.         r.bpos := 0; r.buf := GetBuf (r.file, r.pos);
  462.       ELSE
  463.         r.res := n; r.eof := TRUE; EXIT
  464.       END;
  465.     ELSE
  466.       m := r.buf.lim - r.bpos;
  467.       IF m > 0 THEN
  468.         SYS.MOVE (src, dst, m); r.bpos := r.buf.lim
  469.       END;
  470.       r.res := n - m; r.eof := TRUE; EXIT
  471.     END;
  472.   END; (* LOOP *)
  473. END ReadBytes;
  474.  
  475.  
  476. <*$ < StackChk- IndexChk- *>
  477.  
  478. PROCEDURE SwapWord ( VAR w : ARRAY OF SYS.BYTE );
  479.  
  480.   VAR t : SYS.BYTE;
  481.  
  482. BEGIN (* SwapWord *)
  483.   t := w [0]; w [0] := w [1]; w [1] := t
  484. END SwapWord;
  485.  
  486.  
  487. PROCEDURE SwapLongword ( VAR l : ARRAY OF SYS.BYTE );
  488.  
  489.   VAR t : SYS.BYTE;
  490.  
  491. BEGIN (* SwapLongword *)
  492.   t := l [0]; l [0] := l [3]; l [3] := t;
  493.   t := l [1]; l [1] := l [2]; l [2] := t;
  494. END SwapLongword;
  495.  
  496. <*$ > *>
  497.  
  498.  
  499. PROCEDURE ReadInt * ( VAR r : Rider; VAR x : INTEGER );
  500.  
  501.   VAR i : INTEGER;
  502.  
  503. BEGIN (* ReadInt *)
  504.   ReadBytes (r, i, 2); SwapWord (i); x := i
  505. END ReadInt;
  506.  
  507.  
  508. PROCEDURE ReadLInt * ( VAR r : Rider; VAR x : LONGINT );
  509.  
  510.   VAR i : LONGINT;
  511.  
  512. BEGIN (* ReadLInt *)
  513.   ReadBytes (r, i, 4); SwapLongword (i); x := i
  514. END ReadLInt;
  515.  
  516.  
  517. PROCEDURE ReadReal * ( VAR r : Rider; VAR x : REAL );
  518.  
  519.   VAR y : REAL;
  520.  
  521. BEGIN (* ReadReal *)
  522.   ReadBytes (r, y, 4); SwapLongword (y); x := y
  523. END ReadReal;
  524.  
  525.  
  526. PROCEDURE ReadLReal * ( VAR r : Rider; VAR x : LONGREAL );
  527. BEGIN (* ReadLReal *)
  528.   HALT (99)
  529. END ReadLReal;
  530.  
  531.  
  532. PROCEDURE ReadNum * ( VAR r : Rider; VAR x : LONGINT );
  533.  
  534.   VAR s : SHORTINT; ch : CHAR; n : LONGINT;
  535.  
  536. BEGIN (* ReadNum *)
  537.   s := 0; n := 0; Read(r, ch);
  538.   WHILE ORD(ch) >= 128 DO
  539.     INC(n, ASH(ORD(ch) - 128, s)); INC(s, 7); Read(r, ch)
  540.   END;
  541.   x := n + ASH(ORD(ch) MOD 64 - ORD(ch) DIV 64 * 64, s)
  542. END ReadNum;
  543.  
  544.  
  545. PROCEDURE ReadString * ( VAR r : Rider; VAR x : ARRAY OF CHAR );
  546.  
  547.   VAR ch : CHAR; i : INTEGER;
  548.  
  549. BEGIN (* ReadString *)
  550.   i := 0;
  551.   REPEAT
  552.     Read (r, ch); x [i] := ch; INC (i)
  553.   UNTIL ch = 0X
  554. END ReadString;
  555.  
  556.  
  557. PROCEDURE ReadSet * ( VAR r : Rider; VAR x : SET );
  558.  
  559.   VAR s : SET;
  560.  
  561. BEGIN (* ReadSet *)
  562.   ReadBytes (r, s, 4); SwapLongword (s); x := s
  563. END ReadSet;
  564.  
  565.  
  566. PROCEDURE ReadBool * ( VAR r : Rider; VAR x : BOOLEAN );
  567.  
  568.   VAR i : SHORTINT;
  569.  
  570. BEGIN (* ReadBool *)
  571.   Read (r, i); x := (i # 0)
  572. END ReadBool;
  573.  
  574.  
  575. PROCEDURE Write * ( VAR r : Rider; x : SYS.BYTE );
  576.  
  577.   VAR f : File; buf : Buffer;
  578.  
  579. BEGIN (* Write *)
  580.   ASSERT (r.file # NIL, 97); ASSERT (r.file.fh # NIL, 97);
  581.   IF r.pos # r.buf.apos THEN r.buf := GetBuf (r.file, r.pos) END;
  582.   IF r.bpos >= r.buf.lim THEN
  583.     IF r.bpos < SectorSize THEN
  584.       INC (r.buf.lim); INC (r.file.len)
  585.     ELSE
  586.       f := r.file; INC (r.pos, SectorSize);
  587.       r.buf := GetBuf (f, r.pos);
  588.       IF r.pos >= f.len THEN r.buf.lim := 1; f.len := r.pos END;
  589.       r.bpos := 0
  590.     END
  591.   END;
  592.   r.buf.data [r.bpos] := x; INC (r.bpos); r.buf.mod := TRUE
  593. END Write;
  594.  
  595.  
  596. PROCEDURE WriteBytes * ( VAR r : Rider; VAR x : ARRAY OF SYS.BYTE;
  597.                           n : LONGINT );
  598.  
  599.   VAR src, dst, m : LONGINT; f : File; buf : Buffer;
  600.  
  601. BEGIN (* WriteBytes *)
  602.   ASSERT (r.file # NIL, 97); ASSERT (r.file.fh # NIL, 97);
  603.   ASSERT (LEN (x) >= n, 97);
  604.   src := SYS.VAL (LONGINT, SYS.ADR (x));
  605.   IF r.pos # r.buf.apos THEN r.buf := GetBuf (r.file, r.pos) END;
  606.   LOOP
  607.     IF n <= 0 THEN EXIT END;
  608.     r.buf.mod := TRUE;
  609.     dst := SYS.VAL (LONGINT, SYS.ADR(r.buf.data)); INC (dst, r.bpos);
  610.     m := r.bpos + n;
  611.     IF m <= r.buf.lim THEN
  612.       SYS.MOVE (src, dst, n); r.bpos := SHORT (m); EXIT
  613.     ELSIF m <= SectorSize THEN
  614.       SYS.MOVE (src, dst, n); r.bpos := SHORT (m);
  615.       INC (r.file.len, n); r.buf.lim := SHORT (m); EXIT
  616.     ELSE
  617.       m := SectorSize - r.bpos;
  618.       IF m > 0 THEN
  619.         SYS.MOVE (src, dst, m); INC (src, m); DEC (n, m);
  620.         INC (r.buf.lim, SHORT (m))
  621.       END;
  622.       f := r.file; INC (r.pos, SectorSize);
  623.       r.bpos := 0; r.buf := GetBuf (f, r.pos);
  624.       IF r.pos >= f.len THEN r.buf.lim := 0; f.len := r.pos END;
  625.     END;
  626.   END; (* LOOP *)
  627. END WriteBytes;
  628.  
  629.  
  630. PROCEDURE WriteInt * ( VAR r : Rider; x : INTEGER );
  631. BEGIN (* WriteInt *)
  632.   SwapWord (x); WriteBytes (r, x, 2);
  633. END WriteInt;
  634.  
  635.  
  636. PROCEDURE WriteLInt * ( VAR r : Rider; x : LONGINT );
  637. BEGIN (* WriteLInt *)
  638.   SwapLongword (x); WriteBytes (r, x, 4);
  639. END WriteLInt;
  640.  
  641.  
  642. PROCEDURE WriteReal * ( VAR r : Rider; x : REAL );
  643. BEGIN (* WriteReal *)
  644.   SwapLongword (x); WriteBytes (r, x, 4);
  645. END WriteReal;
  646.  
  647.  
  648. PROCEDURE WriteLReal * ( VAR r : Rider; x : LONGREAL );
  649. BEGIN (* WriteLReal *)
  650.   HALT (99)
  651. END WriteLReal;
  652.  
  653.  
  654. PROCEDURE WriteNum * ( VAR r : Rider; x : LONGINT );
  655. BEGIN (* WriteNum *)
  656.   WHILE (x < -64) OR (x > 63) DO
  657.     Write(r, CHR(x MOD 128 + 128)); x := x DIV 128
  658.   END;
  659.   Write(r, CHR(x MOD 128))
  660. END WriteNum;
  661.  
  662.  
  663. PROCEDURE WriteString * ( VAR r : Rider; x : ARRAY OF CHAR );
  664. <*$CopyArrays-*>
  665. BEGIN (* WriteString *)
  666.   WriteBytes (r, x, str.Length (x)); Write (r, 0X)
  667. END WriteString;
  668.  
  669.  
  670. PROCEDURE WriteSet * ( VAR r : Rider; x : SET );
  671. BEGIN (* WriteSet *)
  672.   SwapLongword (x); WriteBytes (r, x, 4);
  673. END WriteSet;
  674.  
  675.  
  676. PROCEDURE WriteBool * ( VAR r : Rider; x : BOOLEAN );
  677.  
  678.   VAR i : SHORTINT;
  679.  
  680. BEGIN (* WriteBool *)
  681.   IF x THEN i := 1 ELSE i := 0 END; Write (r, i)
  682. END WriteBool;
  683.  
  684.  
  685. PROCEDURE* CloseFiles ( VAR rc : LONGINT );
  686.  
  687. BEGIN (* CloseFiles *)
  688.   WHILE root # NIL DO
  689.     IF root.fh # NIL THEN
  690.       Unbuffer (root);
  691.       IF d.Close (root.fh) THEN END;
  692.       d.UnLock (root.fl);
  693.     END;
  694.     root := root.next
  695.   END;
  696. END CloseFiles;
  697.  
  698.  
  699. BEGIN (* Files *)
  700.   root := NIL; GetTempNo; Kernel.SetCleanup (CloseFiles);
  701. END Files.
  702.